package com.heima.user.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.jwt.JWTUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.dtos.LoginDto;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.user.vos.LoginVo;
import com.heima.user.mapper.ApUserMapper;
import com.heima.user.service.ApUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.HashMap;
import java.util.Map;

@Service
public class ApUserServiceImpl extends ServiceImpl<ApUserMapper, ApUser> implements ApUserService {

    // apUser
    @Autowired
    private ApUserMapper apUserMapper;

    @Override
    public ResponseResult login(LoginDto dto) {
        // 0. 参数判断
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        // 1. 提取前端传过来的手机号和密码
        // 如果手机号和密码同时不存在，那么就代表是游客登录 -> 否则就是正常登录
        String phone = dto.getPhone();
        String password1 = dto.getPassword();

        if (StrUtil.isBlank(phone) && StrUtil.isBlank(password1)) {
            // 游客登录

            // 4. 生成token(使用id=0生成)
            Map<String, Object> map = new HashMap<>();
            // 为了能够区分正常登录和游客登录
            map.put("id", "0");
            String token = JWTUtil.createToken(map, "leadnews".getBytes());

            // 5. 组装返回值结构，并返回LoginVo结构
            LoginVo vo = new LoginVo();
            vo.setToken(token);
            vo.setUser(null);

            return ResponseResult.okResult(vo);
        }

        // 正常登录（手机号+密码登录）
        else {
            // 1. 到数据库查询用户（使用手机号作为条件）

            // ApUser::getPhone ->  ApUser apuser = new ApUser(); apuser.getPhone();
            // myBatisPlus的语法，构建一个查询条件 -> WHERE
            LambdaQueryWrapper<ApUser> wrapper = new LambdaQueryWrapper<>();
            // eq -> equals -> 是否相等
            // WHERE phone = dto.getPhone();
            wrapper.eq(ApUser::getPhone, dto.getPhone());
            // SELECT id,phone FROM ap_user + WHERE phone = dto.getPhone() -> 执行SQL -> 查询结果
            ApUser apUser = apUserMapper.selectOne(wrapper);
            if (apUser == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
            }

            String password = apUser.getPassword();
            // 2. 比对密码
            // 拿数据库中已MD5的密码 和 前端传过来的密码作比对
            // 注意：前端传过来的密码，要先MD5一下才能比对
            String passwordFromFront = dto.getPassword();
            // MD5(密码+盐)
            String salt = apUser.getSalt();
            String passwordAfterHash = DigestUtils.md5DigestAsHex((passwordFromFront + salt).getBytes());
            if (!passwordAfterHash.equals(password)) {
                return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);
            }

            // 3. 返回数据(LoginVo结构：包含user信息和token)

            // 生成token的动作 hutool
            // 参数一：Map结构，存储在token里面的用户信息
            // 参数二：秘钥 -> 一个字符串，用来加密token用的
            Map<String, Object> userInfo = new HashMap<>();
            userInfo.put("id", apUser.getId());
            String token = JWTUtil.createToken(userInfo, "leadnews".getBytes());

            LoginVo vo = new LoginVo();

            // 为了安全考虑，密码和盐不能展示给前端
            apUser.setSalt(null);
            apUser.setPassword(null);

            vo.setUser(apUser);
            vo.setToken(token);

            return ResponseResult.okResult(vo);
        }

    }

}